#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;


// <method_statement> ~ <variable_definition>  {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, trace}
// <method_statement> ~ <assignment>  {NAME}
// <method_statement> ~ <method_call>  {NAME}
// <method_statement> ~ <if_statement>  {if}
// <method_statement> ~ <while_statement>  {while}
// <method_statement> ~ <for_statement>  {for}
// <method_statement> ~ <dowhile_statement>  {do}
// <method_statement> ~ <switch_case_statement>  {switch}
// <method_statement> ~ <break_statement>  {break}
// <method_statement> ~ <continue_statement>  {continue}
// <method_statement> ~ <goto_statement>  {goto}
// <method_statement> ~ <start_statement>  {start}
// <method_statement> ~ <stop_statement>  {stop}
// <method_statement> ~ <assignment_derivation>  {derivation}
// <method_statement> ~ <return_statement>  {return}
// <method_statement> ~ <block_statement>  {{}
// <method_statement> ~ ? {}}

void Parser::Parse_MethodStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_MethodStatement");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// get next two units
	LexicUnit nextUnit1, nextUnit2;
	nextUnit1 = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 1);
	nextUnit2 = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 2);

	int chouseProduction = -1;
	int error = -1;
	int lexicPosition = this->CurrentLexicPosition;
 

	//current position
	int i=0;

	// if currentUnit is NAME 
	if (currentUnit.type == LUTypeIdentifier)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"NAME\"");
#endif
		if (nextUnit1.subtype == LUTypeSpecialCharacter && nextUnit1.subtype == SpecialCharacterLeftParenthesis)
		{

			chouseProduction = 3;
			
		}
		else  
		{

			// parse <name>
			do
			{
				// get lexic unit
				currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition+1);
				nextUnit1 = CompilerData->Units->GetLexicUnit(lexicPosition+2);
				
				// if lexic unit is endOfFile
				if((currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
					||(nextUnit1.type == LUTypeSpecialType && nextUnit1.subtype == endOfFile))
				{
					error = 1;
					break;
				}
				//skip <name>  {NAME.NAME. ... .NAME} or only {NAME}
				else if(
					(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod) &&
					(nextUnit1.type == LUTypeIdentifier)
					)
				{
					lexicPosition += 2;
					continue;
				}
				else
				{
					break;
				}

			}
			while(1);

			if(error != 1)
			{
				// if next < or NAME then is <variable_definition>
				if ((currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorLessThan) || (currentUnit.type == LUTypeIdentifier))
				{
					chouseProduction = 1;
				}
				else 
				{
					//read forward 
					while (1)
					{
						currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition);
						// if iz endOfFile or ';' then exit
						if (currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
						{
							error = 1;
							break;
						}
						else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
						{
							// DOPUNITI: 
							// 1. prijava errora da nije dobra naredba unutar <method_statement>-a
							//Napraviti!
							CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_METHOD_STATEMENT_PARSE);

							// 2. oporavak od pogreske:
							chouseProduction = 3;
							break;
						}
						//if is '=' then is <assignment>
						else if (currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorAssigment)
						{
							chouseProduction = 2;
							break;
						}
						//if is '(' then is <method_call>  
						else if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
						{
							chouseProduction = 3;
							break;
						}
						lexicPosition++;

					}
				}
			}
		}

		if(chouseProduction == 1)
		{
			// write type of production in this node
			parent->Production = Gr_MethodStatement__VariableDefinition;

			// process nonterminal symbol <variable_definition> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_VariableDefinition(newNode0);
		}
		else if(chouseProduction == 2)
		{
			// write type of production in this node
			parent->Production = Gr_MethodStatement__Assignment;

			// process nonterminal symbol <assignment> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_Assignment(newNode0);

		}
		else if(chouseProduction == 3)
		{
			// write type of production in this node
			parent->Production = Gr_MethodStatement__MethodCall;

			// process nonterminal symbol <method_call> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_MethodCall(newNode0);
		}
		
	}


	else if((currentUnit.type == LUTypeKeyword && (
		currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat ||
		currentUnit.subtype == KeywordBool ||
		currentUnit.subtype == KeywordState ||
		currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid ||
		currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage ||
		currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable ||
		currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordOutputStream||
        currentUnit.subtype == KeywordTrace))
		)
	{
		// write type of production in this node
		parent->Production = Gr_MethodStatement__VariableDefinition;

		// process nonterminal symbol <variable_definition> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_VariableDefinition(newNode0);

	}

	else if(

		//currentUnit == if
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"If\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__IfStatement;

		// process nonterminal symbol <if_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_IfStatement(newNode0);

	}
		
	else if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \"}\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__epsilon;
	}

	else if(

		//currentUnit == while
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWhile 
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"While\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__WhileStatement;

		// process nonterminal symbol <while_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_WhileStatement(newNode0);

	}

	else if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \"{\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__BlockStatement;
		// process nonterminal symbol <block_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_BlockStatement(newNode0);
	}

	else if(

		//currentUnit == for
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordFor
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"For\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__ForStatement;

		// process nonterminal symbol <for_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ForStatement(newNode0);

	}

	else if(

		//currentUnit == do
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDo
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Do\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__DowhileStatement;

		// process nonterminal symbol <dowhile_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_DowhileStatement(newNode0);

	}

	else if(

		//currentUnit == switch
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSwitch
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Switch\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__SwitchCaseStatement;

		// process nonterminal symbol <switch_case_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SwitchCaseStatement(newNode0);

	}

	else if(

		//currentUnit == break
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordBreak
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Break\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__BreakStatement;

		// process nonterminal symbol <break_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_BreakStatement(newNode0);

	}

	else if(

		//currentUnit == continue
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordContinue
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Continue\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__ContinueStatement;

		// process nonterminal symbol <continue_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ContinueStatement(newNode0);

	}

	else if(

		//currentUnit == goto
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGoto
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Goto\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__GotoStatement;

		// process nonterminal symbol <goto_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_GotoStatement(newNode0);

	}

	else if(

		//currentUnit == start
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordStart
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Start\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__StartStatement;

		// process nonterminal symbol <start_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_StartStatement(newNode0);

	}

	else if(

		//currentUnit == stop
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordStop
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Stop\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__StopStatement;

		// process nonterminal symbol <stop_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_StopStatement(newNode0);

	}

	else if(

		//currentUnit == derivation
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDerivation
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"Derivation\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__AssignmentDerivation;

		// process nonterminal symbol <assignment_derivation> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_AssignmentDerivation(newNode0);

	}
	else if(

		//currentUnit == return
		currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordReturn
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"return\"");
#endif
		// write type of production in this node
		parent->Production = Gr_MethodStatement__ReturnStatement;

		// process nonterminal symbol <return_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ReturnStatement(newNode0);

	}

	else if(error == 1)
	{
		// Error endofFile
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNEXPECTED_END_OF_FILE);
	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_METHOD_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_MethodStatement");
#endif
}



// <assignment> ~ <variable_value> = <expression> ;  {NAME}
void Parser::Parse_Assignment(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_Assignment");
#endif
	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(
		//currentUnit == NAME
		currentUnit.type == LUTypeIdentifier
		)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"NAME\"");
#endif
		// write type of production in this node
		parent->Production = Gr_Assignment__VariableValue_opAssign_Expression_spSemiCol;

		// process nonterminal symbol <variable_value> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_VariableValue(newNode0);

		// process terminal symbol '=' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		//if( /* currentUnit == = */ )
		if (currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorAssigment )
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized OperatorAssigment");
#endif

			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ASSIGNMENT_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		//if( /* currentUnit == ; */ )
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterSemicolon");
#endif
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ASSIGNMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_Assignment");
#endif
}


// <simple_statement> ~ <data_type> <field_names>  {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
// <simple_statement> ~ <variable_value> = <expression>  {NAME}
// <simple_statement> ~ NAME ( <arguments> )  {NAME}
// <simple_statement> ~ <variable_value> . NAME ( <arguments> )  {NAME}
void Parser::Parse_SimpleStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimpleStatement");
#endif
	LexicUnit currentUnit;	
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// get next two unit
	LexicUnit nextUnit1, nextUnit2;
	nextUnit1 = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 1);
	nextUnit2 = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 2);
	int i=0;

	int chouseProduction = -1;
	int error = -1;
	int lexicPosition = this->CurrentLexicPosition;

	// if is NAME
	if (currentUnit.type == LUTypeIdentifier)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"NAME\"");
#endif
		// if the next unit is '(' then is <simple_statement> ~ NAME ( <Arguments> )  {NAME}
		if (nextUnit1.type == LUTypeSpecialCharacter && nextUnit1.subtype == SpecialCharacterLeftParenthesis)
		{
			chouseProduction = 3;
		}
		else 
		{			
			//try skip <name>
			do
			{
				// get lexic unit
				currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition+1);
				nextUnit1 = CompilerData->Units->GetLexicUnit(lexicPosition+2);
				
				// if lexic unit is endOfFile
				if((currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
					||(nextUnit1.type == LUTypeSpecialType && nextUnit1.subtype == endOfFile))
				{
					error = 1;
					break;
				}
				//skip <name>  {NAME.NAME. ... .NAME} or only {NAME}
				else if(
					(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod) &&
					(nextUnit1.type == LUTypeIdentifier)
					)
				{
					lexicPosition += 2;
					continue;
				}
				else
				{
					break;
				}

			}
			while(1);

			if(error != 1)
			{
				// if next unit is '<' then skip all units to '>'
				if (currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorLessThan)
				{
					while (1)
					{
						
						currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition+1);
						if(currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
						{
							error = 1;
							break;
						}
						else if (currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorGreaterThan)
						{
							break;
						}
						lexicPosition++;

					}
					if(error != 1)
					{
						currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition+1);
						// if is NAME
						if (currentUnit.type == LUTypeIdentifier)
						{
							chouseProduction = 1;
						}
					}
				}
				else if ( currentUnit.type == LUTypeIdentifier )
				{
					chouseProduction = 1;
				}
				else 
				{
					// 2 or 4 
					chouseProduction = 0;
				}
			}
		}
	}

	if(
		/*
		currentUnit == int
		currentUnit == float
		currentUnit == bool
		currentUnit == state
		currentUnit == time
		currentUnit == void
		currentUnit == Facility
		currentUnit == Storage
		currentUnit == Queue
		currentUnit == ADTable
		currentUnit == Group
		currentUnit == OutputStream
		currentUnit == NAME*/
		(currentUnit.type == LUTypeKeyword && (
		currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat ||
		currentUnit.subtype == KeywordState ||
		currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid ||
		currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage ||
		currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable ||
		currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordOutputStream) ||
		(chouseProduction == 1 ))
		)

	{
		// write type of production in this node
		parent->Production = Gr_SimpleStatement__DataType_FieldNames;

		// process nonterminal symbol <data_type> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_DataType(newNode0);

		// process nonterminal symbol <field_names> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_FieldNames(newNode1);

	}

	else if(

		//currentUnit == NAME
		chouseProduction == 0

		)
	{
		// write type of production in this node
		//parent->Production =//...

		// process nonterminal symbol <variable_value> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_VariableValue(newNode0);

		// process terminal symbol '=' or '.' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if( // currentUnit == = */ )
		if (currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorAssigment)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized OperatorAssigment");
#endif

			parent->Production = Gr_SimpleStatement__VariableValue_opAssign_Expression;

			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

			// process nonterminal symbol <expression> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_Expression(newNode2);
		}
		else if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterPeriod");
#endif

			parent->Production = Gr_SimpleStatement__VariableValue_spPer_NAME_spLPar_Arguments_spRPar;

			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;


			// process terminal symbol 'NAME' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			//if( /* currentUnit == NAME */ )
			if (currentUnit.type == LUTypeIdentifier)
			{
#ifdef TRACE
				CompilerData->LogTrace->ReportLine("Recognized keyword \"NAME\"");
#endif
				SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode2);
				newNode2->LexUnitID=this->CurrentLexicPosition;
				newNode2->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process terminal symbol '(' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			//if( /* currentUnit == ( */ )
			if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
			{
#ifdef TRACE
				CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftParenthesis");
#endif

				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				newNode3->LexUnitID=this->CurrentLexicPosition;
				newNode3->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process nonterminal symbol <arguments> 
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			Parse_Arguments(newNode4);

			// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			//if( /* currentUnit == ) */ )
			if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
			{
#ifdef TRACE
				CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis");
#endif
				SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode5);
				newNode5->LexUnitID=this->CurrentLexicPosition;
				newNode5->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
	}


	else if(

		//currentUnit == NAME
		chouseProduction == 3
		)
	{
		// write type of production in this node
		parent->Production = Gr_SimpleStatement__NAME_spLPar_Arguments_spRPar;

		// process terminal symbol 'NAME' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		//if( /* currentUnit == ( */ )
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
#ifdef TRACE
				CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftParenthesis");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <arguments> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Arguments(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		//if( /* currentUnit == ) */ )
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
		{
#ifdef TRACE
				CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis");
#endif

			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	else if(error == 1)
	{
		// Error endOfFile
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNEXPECTED_END_OF_FILE);
	}

	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIMPLE_STATMENT_BEGINING);
		// REPORT ERROR
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimpleStatement");
#endif

}
